package com.quercus.util;

import com.quercus.dao.CustomerDao;
import com.quercus.dao.UserDao;
import com.quercus.entity.Customer;
import com.quercus.entity.User;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.io.OutputFormat;
import org.dom4j.io.SAXReader;
import org.dom4j.io.XMLWriter;

import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.io.Writer;
import java.lang.reflect.Constructor;
import java.lang.reflect.Method;
import java.util.List;

/**
 * @author quercus
 */
public class XmlUtil {
    public static String url = XmlUtil.class.getResource("/").getPath();
    public static String fileName = url + "beans.xml";

    /**
     * 读取指定xml文件生成DOM树并返回
     *
     * @param fileName
     * @return
     */
    public static Document readFile(String fileName) {
        //根据XML创建一个DOM树
        SAXReader reader = new SAXReader();
        File file = new File(fileName);
        Document doc = null;
        try {
            doc = reader.read(file);
        } catch (DocumentException e) {
            e.printStackTrace();
        }
        return doc;
    }

    /**
     * 写DOM树最新内容到XML文件
     *
     * @param doc
     * @param fileName
     */
    public static void writeFile(Document doc, String fileName) {
        //精致美观
        OutputFormat format = OutputFormat.createPrettyPrint();
        format.setEncoding("UTF-8");
        XMLWriter xmlWriter = null;
        try {
            Writer fw = new FileWriter(fileName);
            xmlWriter = new XMLWriter(fw, format);
            xmlWriter.write(doc);
        } catch (IOException e) {
            e.printStackTrace();
            //异常链:捕获检查异常，抛出运行时异常
            throw new RuntimeException(e.getMessage());
        } finally {
            try {
                if (xmlWriter != null) {
                    xmlWriter.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    /**
     * 使用反射实现参数注入模拟Spring
     */
    public static <T> T getInstance(String beanId) {
        T t = null;
        Document doc = readFile(fileName);
        List<Element> beanElemList = doc.getRootElement().elements("bean");
        String className = null;
        Element propertyElem = null;
        Element constructorArgElem = null;
        for (Element beanElem : beanElemList) {
            String beanId2 = beanElem.attribute("id").getValue();
            if (beanId2.equals(beanId)) {
                //获取类的名字
                className = beanElem.attribute("class").getValue();
                //获取属性名和属性值
                propertyElem = beanElem.element("property");
                //获取属性名和属性值
                constructorArgElem = beanElem.element("constructor-arg");
                break;
            }
        }

        try {
            if (propertyElem != null) {
                //优先使用setter方法注入属性
                //使用反射创建对象
                Class clazz2 = Class.forName(className);
                t = (T) clazz2.getConstructor().newInstance();
                String name = propertyElem.attribute("name").getValue();
                String value = propertyElem.attribute("value").getValue();
                String methodName = "set" + name.substring(0, 1).toUpperCase() + name.substring(1);
                Method method = clazz2.getMethod(methodName, String.class);
                method.invoke(t, value);
            } else if (constructorArgElem != null) {
                //无setter方法，就使用参数构造方法注入
                Class clazz2 = Class.forName(className);
                String value = constructorArgElem.attribute("value").getValue();
                t = (T) clazz2.getConstructor(String.class).newInstance(value);
            } else {//只有采用默认值了
                Class<?> clazz2 = Class.forName(className);
                t = (T) clazz2.getConstructor().newInstance();
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return t;
    }

    public static void main(String[] args) {
        try {
            CustomerDao customerDao = XmlUtil.getInstance("customerDao");
            List<Customer> list = customerDao.findAll();
            list.forEach(System.out::println);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}
